import React from 'react';
import pcapWsParse from 'pcap-ws-parse';
import { Upload, Table, Input, Modal } from 'antd';
import { InboxOutlined } from '@ant-design/icons';
import { ColumnProps } from 'antd/es/table';
import ReactJson from 'react-json-view'
import { IState, TLists, TUploadProps } from '../../types/ParserWrap';
import moment from 'moment';

const formatTime = (timestamp: number): string => {
	return moment(timestamp).format('YYYY-MM-DD HH:mm:ss');
}

const { Search } = Input;
const { Dragger } = Upload;
function getArrayBuffer(file: any): Promise<any> {// 读取文件内容
	return new Promise((resolve, reject) => {
		const reader = new FileReader();
		reader.readAsArrayBuffer(file);
		reader.onload = () => resolve(reader.result);
		reader.onerror = error => reject(error);
	});
}
class ParserWrap extends React.Component<any, IState> {
	constructor(props: any) {
		super(props);
		this.state = {
			protocol: [{
				text: '',
				value: ''
			}],
			destination: [{
				text: '',
				value: ''
			}],
			source: [{
				text: '',
				value: ''
			}],
			filteredInfo: [],
			visible: false,
			dataSource: [],
			lists: [],
			fileListMap: new Map<string, any>(),
			info: {}
		};
	}
	parser = async (file: any) => {// pcap-ws-parse处理文件内容，并获取解析数据
		let tempMap = this.state.fileListMap;
		let pcapCon: any;
		let tempPcapLists: Array<any> = [];
		if (tempMap.has(file.name)) {
			pcapCon = tempMap.get(file.name);
		} else {
			const result = await getArrayBuffer(file);
			const pcapArr = new Uint8Array(result as Iterable<number>);
			const ret = pcapWsParse(pcapArr);

			console.log(ret);

			pcapCon = ret.pcapBody;
			tempMap.set(file.name, pcapCon);
			this.setState({ fileListMap: tempMap });
		}
		let protocol = new Set();
		let destination = new Set();
		let source = new Set();
		pcapCon.forEach((item: any, index: number) => {
			protocol.add(item.protocol)
			destination.add(item.packetBody.NetWork.DIP)
			source.add(item.packetBody.NetWork.SIP)
			let body = item.packetBody.Application.body;

			console.log(item.packetHeaders.timestampHigh, formatTime(item.packetHeaders.timestampHigh * 1000))

			let json: TLists = {
				FrameNum: item.FrameNum,
				time: `${formatTime(item.packetHeaders.timestampHigh * 1000)}.${item.packetHeaders.timestampLow}`,
				source: item.packetBody.NetWork.SIP,
				destination: item.packetBody.NetWork.DIP,
				protocol: item.protocol,
				length: item.packetHeaders.Len,
				info: {
					headers: item.packetBody.Application.headers ? item.packetBody.Application.headers : '',
					body: body ? (Object.prototype.toString.call(body) === '[object Uint8Array]' ? 'Unit8Array[]' : body) : ''
				}
			}
			tempPcapLists.push(json);
		});
		let protocolKeywords: Array<any> = []
		protocol.forEach(item => {
			let json = {
				text: item,
				value: item
			}
			protocolKeywords.push(json)
		})
		let destinationKeywords: Array<any> = []
		destination.forEach(item => {
			let json = {
				text: item,
				value: item
			}
			destinationKeywords.push(json)
		})
		let sourceKeywords: Array<any> = []
		source.forEach(item => {
			let json = {
				text: item,
				value: item
			}
			sourceKeywords.push(json)
		})
		this.setState({ lists: tempPcapLists, dataSource: tempPcapLists, protocol: protocolKeywords, source: sourceKeywords, destination: destinationKeywords })
	}
	search = (searchText: string) => {// 搜索
		if (searchText === '') {
			this.setState({ lists: this.state.dataSource });
			return;
		};
		const dataSource = this.state.dataSource;
		// eslint-disable-next-line
		const searchTextLowerCase = searchText.toLowerCase();
		const result = dataSource.filter((item) => {
			for (let val of Object.values(item)) {
				if (typeof val === 'string') {
					if (val.toString().toLowerCase().includes(searchTextLowerCase)) {
						return true;
					}
				}

				if (typeof val === 'object') {
					if (JSON.stringify(val).toLowerCase().includes(searchTextLowerCase)) {
						return true;
					}
				}
			}
		});
		this.setState({ lists: result })
	}
	openModal = (info: object): void => {// 抓包详情弹窗
		this.setState({
			info,
			visible: true
		});
	}

	closeModal = (e: any) => {
		this.setState({
			visible: false
		});
	};
	filterChange = (pagination: any, filters: any) => {
		this.setState({
			filteredInfo: filters
		});
	};
	render() {
		const filteredInfo: any = this.state.filteredInfo;
		const protocol: any = this.state.protocol;
		const destination: any = this.state.destination;
		const source: any = this.state.source;
		const columns: ColumnProps<TLists>[] = [
			{
				title: '序号',
				dataIndex: 'FrameNum',
				key: 'FrameNum',
				sorter: (a, b) => a.FrameNum - b.FrameNum
			},
			{
				title: 'time',
				dataIndex: 'time',
				key: 'time',
				sorter: (a, b) => a.time.localeCompare(b.time)
			},
			{
				title: 'source',
				dataIndex: 'source',
				key: 'source',
				filters: source,
				filteredValue: filteredInfo.source || null,
				onFilter: (value, record: any) => { return record.source.includes(value) }
			},
			{
				title: 'destination',
				dataIndex: 'destination',
				key: 'destination',
				filters: destination,
				filteredValue: filteredInfo.destination || null,
				onFilter: (value, record: any) => { return record.destination.includes(value) }
			},
			{
				title: 'protocol',
				dataIndex: 'protocol',
				key: 'protocol',
				filters: protocol,
				filteredValue: filteredInfo.protocol || null,
				onFilter: (value, record: any) => { return record.protocol.includes(value) }
			},
			{
				title: 'length',
				dataIndex: 'length',
				key: 'length',
				sorter: (a, b) => a.length - b.length
			},
			{
				title: 'info',
				dataIndex: 'info',
				key: 'info',
				render: (text, record) => (
					<span>
						<span className="ellipsis">{JSON.stringify(text.body)}</span>
						<a href="javascript:void(0)" onClick={() => this.openModal(text)}>详情</a>
					</span>
				)
			}
		];
		const props: TUploadProps = {// 上传组件属性
			showUploadList: false,
			mutiple: false,
			beforeUpload: this.parser
		};
		return (
			<div >
				<Dragger {...props}>
					<p className="ant-upload-drag-icon">
						<InboxOutlined />
					</p>
					<p className="ant-upload-text">点击或拖拽文件到此区域上传文件</p>
				</Dragger>
				<div className="table-operations">
					<Search
						placeholder="输入ip/proto进行过滤"
						onSearch={this.search}
						// disabled={this.state.lists.length<1}
						style={{ width: 300 }}
					/>
				</div>
				<Table<TLists> columns={columns} dataSource={this.state.lists} size="small" onChange={this.filterChange} locale={{ filterConfirm: "确定", filterReset: "重置" }}></Table>
				<Modal
					title="数据"
					visible={this.state.visible}
					onOk={this.closeModal}
					onCancel={this.closeModal}
					wrapClassName="parserwrap"
				>
					<ReactJson src={this.state.info} displayObjectSize={false} name={false} displayDataTypes={false} collapseStringsAfterLength={50} indentWidth={4}></ReactJson>
				</Modal>
			</div>
		);
	}
}
export default ParserWrap;